#ifndef _MUTEXT_H_
#define _MUTEXT_H_

#include "netfwd.h"
#include "time_value.h"

#pragma once

class Null_Mutex
{
public:
    Null_Mutex() {}

    ~Null_Mutex() throw() {}

    inline int acquire() { return 0; }

    inline int acquire( const Time_Value & timeout ) { UNUSE_ARG(timeout); return 0; }

    inline int release() { return 0; }
};

class Thread_Mutex
{
public:
	Thread_Mutex();
	Thread_Mutex( const pthread_mutexattr_t * mutex_attr,
				  const pthread_condattr_t * cond_attr );

    ~Thread_Mutex() throw();

    int acquire();

    int acquire( const Time_Value & timeout );

    int release();

	void wait() const;

	void wait( const Time_Value & delay ) const;

	void notify();

	void notify_all();

    operator pthread_mutex_t*() const
    {
        return &m_lock;
    }

private:
    bool                m_remove;       /* avoid multiple calls */
    mutable pthread_mutex_t     m_lock;
	mutable pthread_cond_t		m_cond;

private:
    Thread_Mutex( const Thread_Mutex & );
    const Thread_Mutex & operator= ( const Thread_Mutex & );
};

class Thread_RW_Mutex
{
public:
    Thread_RW_Mutex( const pthread_rwlockattr_t * attr = 0 );

    ~Thread_RW_Mutex() throw();

    int wr_acquire();

    int rd_acquire();

    int release();

private:
    pthread_rwlock_t    m_lock;

private:
    Thread_RW_Mutex( const Thread_Mutex & );
    const Thread_RW_Mutex & operator= ( const Thread_RW_Mutex & );
};

template< typename LOCK_TYPE >
class Guard
{
public:
    Guard( LOCK_TYPE & lock );

    ~Guard() throw();
private:
    LOCK_TYPE *     m_lock;
    int             m_owner;

private:
    Guard( const Guard & );
    const Guard & operator= ( const Guard & );
};

template< typename LOCK_TYPE >
Guard<LOCK_TYPE>::Guard( LOCK_TYPE & lock )
    : m_lock( &lock ),
      m_owner( 0 )
{
    m_owner = m_lock->acquire();
}

template< typename LOCK_TYPE >
Guard<LOCK_TYPE>::~Guard() throw()
{
    if( -1 != m_owner )
    {
        m_lock->release();
    }
}

class Write_Guard
{
public:
    explicit Write_Guard( Thread_RW_Mutex & lock );
    ~Write_Guard() throw();

private:
    Thread_RW_Mutex *   m_lock;
    int                 m_owner;

private:
    Write_Guard( const Write_Guard & );
    const Write_Guard & operator= ( const Write_Guard & );
};

class Read_Guard
{
public:
    explicit Read_Guard( Thread_RW_Mutex & lock );
    ~Read_Guard() throw();

private:
    Thread_RW_Mutex *   m_lock;
    int                 m_owner;

private:
    Read_Guard( const Read_Guard & );
    const Read_Guard & operator= ( const Read_Guard & );
};


#endif // _MUTEXT_H_

